package com.zte.claa.inficombo.csa.app.service.jsplugin.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.zte.claa.inficombo.csa.app.service.jsplugin.CSAJSPluginService;
import com.zte.claa.inficombo.csa.app.util.IOUtils;

@Service
public class CSAJSPluginServiceImpl implements CSAJSPluginService {
	// 相对于 resource目录下面的路径(/js/plugin/<devtypes>.js)
	public static final String JS_PLUGIN_FILEPATH = "js/plugin/";
	// 日志记录.
	private Logger logger = LoggerFactory.getLogger(CSAJSPluginServiceImpl.class);
	
	/**
	 * 设备类型插件映射表 （按需加载策略，懒加载模式）
	 * key: devtypeId;
	 * val: Invocable;
	 */
	private Map<String, Invocable> pluginMap = new HashMap<String, Invocable>();

	@Override
	public Invocable getJsPLugin(String devTypeId) {
		Invocable pnp = this.pluginMap.get(devTypeId);
		if(pnp != null){
			return pnp;
		}
		return this.reloadJsPlugin(devTypeId);
	}
	
    /**
     * 刷新Js插件缓存
     * 
     * @param devTypeId
     * @return
     */
    public synchronized void refreshJsPLugin(String devTypeId) {
    	Reader r = null;
    	InputStream in = null;
        try {
            ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("nashorn");
            String pluginFilePath = JS_PLUGIN_FILEPATH + devTypeId + ".js";
            in = IOUtils.loadClassPathResource(pluginFilePath);
            r = new BufferedReader(new InputStreamReader(in));
            jsEngine.eval(r);
            Invocable invocable = (Invocable)jsEngine;
            this.pluginMap.put(devTypeId, invocable);
        } catch (Exception e) {
            logger.error("refreshJsPLugin for devtype[" + devTypeId + "] failed: " + e.getMessage(), e);
        } finally {
        	if(in != null){
        		try {
					in.close();					
				} catch (IOException e){}  
        		in = null;
        	}
        	if(r != null){
        		try {
					r.close();					
				} catch (IOException e){}  
        		r = null;
        	}
        }
    }	
	
	/**
	 * 懒加载策略
	 * 
	 * @param devTypeId
	 * @return
	 */
	private synchronized Invocable reloadJsPlugin(String devTypeId) {
		// 再尝试获取一次.
		Invocable pnp = this.pluginMap.get(devTypeId);
		if (pnp != null) {
			return pnp;
		}
		Reader r = null;
		InputStream in = null;
		try {
			ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("nashorn");
			String pluginFilePath = JS_PLUGIN_FILEPATH + devTypeId + ".js";
			in = IOUtils.loadClassPathResource(pluginFilePath);
            r = new BufferedReader(new InputStreamReader(in));
			jsEngine.eval(r);
			Invocable invocable = (Invocable) jsEngine;
			this.pluginMap.put(devTypeId, invocable);
			return invocable;
		} catch (Exception e) {
			logger.error("reloadJsPlugin for devtype[" + devTypeId + "] failed: " + e.getMessage(), e);
		} finally {
			if(in != null){
        		try {
					in.close();					
				} catch (IOException e){}  
        		in = null;
        	}
			if(r != null){
        		try {
					r.close();					
				} catch (IOException e){}     
        		r = null;
        	}
		}
		return null;
	}

}
